<!doctype html>
<html lang="zh-cn">
<head>

    <meta charset="utf-8">
    <meta name="generator" content="Hugo 0.57.2" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1">

    <title>V语言从入门到入门 | The Sky of OtsWang</title>
    <meta property="og:title" content="V语言从入门到入门 - The Sky of OtsWang">
    <meta property="og:type" content="article">
        
    <meta property="article:published_time" content="2019-06-26T16:24:39&#43;08:00">
        
        
    <meta property="article:modified_time" content="2019-06-26T16:24:39&#43;08:00">
        
    <meta name="Keywords" content="golang,go语言,otswang,java,博客,python">
    <meta name="description" content="V语言从入门到入门">
        
    <meta name="author" content="OtsWang">
    <meta property="og:url" content="https://otswang.gitee.io/hugo/post/lang/v_starter/">
    <link rel="shortcut icon" href="/favicon.ico" type="image/x-icon">

    <link rel="stylesheet" href="/hugo/css/normalize.css">
    
        <link rel="stylesheet" href="/hugo/css/prism.css">
    
    <link rel="stylesheet" href="/hugo/css/style.css">
    <script type="text/javascript" src="//cdn.bootcss.com/jquery/3.2.1/jquery.min.js"></script>

    


    
    
</head>

<body>
<header id="header" class="clearfix">
    <div class="container">
        <div class="col-group">
            <div class="site-name ">
                
                    <a id="logo" href="https://otswang.gitee.io/hugo/">
                        The Sky of OtsWang
                    </a>
                
                <p class="description">擅长写HelloWorld的小小码农</p>
            </div>
            <div>
                <nav id="nav-menu" class="clearfix">
                    
                    
                    <a  href="https://otswang.gitee.io/hugo/" title="Home">Home</a>
                    
                    <a  href="https://otswang.gitee.io/hugo/tags/" title="Tags">Tags</a>
                    
                    <a  href="https://otswang.gitee.io/hugo/categories/" title="Categories">Categories</a>
                    
                    <a  href="https://otswang.gitee.io/hugo/archives/" title="Archives">Archives</a>
                    
                    <a  href="https://otswang.gitee.io/hugo/about/" title="About">About</a>
                    
                </nav>
            </div>
        </div>
    </div>
</header>


<div id="body">
    <div class="container">
        <div class="col-group">

            <div class="col-8" id="main">
                <div class="res-cons">
                    <article class="post">
                        <header>
                            <h1 class="post-title">V语言从入门到入门</h1>
                        </header>
                        <date class="post-meta meta-date">
                            2019年6月26日
                        </date>
                        
                        <div class="post-meta">
                            <span>|</span>
                            
                                <span class="meta-category"><a href="https://otswang.gitee.io/hugo/categories/%E5%B0%8F%E4%BC%97%E8%AF%AD%E8%A8%80%E4%B8%80%E7%9E%A5">小众语言一瞥</a></span>
                            
                        </div>
                        
                        
                        
                        <div class="post-content">
                            <p>最近比较火的v语言，学习一下。官方教程。</p>

<h2 id="introduction">Introduction</h2>

<p>V is a statically typed compiled programming language designed for building maintainable software.</p>

<p>It&rsquo;s similar to Go and is also influenced by Oberon, Rust, Swift.</p>

<pre><code class="language-v">/* Hello World */
fn main() {
	println('hello world')
}
</code></pre>

<p>Functions are declared with <code>fn</code>. Return type goes after the function name. In this case main doesn&rsquo;t return anything, so the type is omitted. (similar with go)</p>

<p>Just like in C and all related languages, <code>main</code> is an entry point.</p>

<p><code>println</code> is one of the few built-in functions. It prints the value to standard output.</p>

<p><code>fn main()</code> declaration can be skipped in one file programs. This is useful when writing small programs, &ldquo;scripts&rdquo;, or just learning the language. For brevity, <code>fn main()</code> will be skipped in this tutorial.</p>

<p>This means that a &ldquo;hello world&rdquo; program can be as simple as</p>

<pre><code class="language-v">println('hello world')
</code></pre>

<h2 id="functions">Functions</h2>

<pre><code>fn main() {
	println(add(77, 33))
	println(sub(100, 50))
}

fn add(x int, y int) int {
	return x + y
}

fn sub(x, y int) int {
	return x - y
}
</code></pre>

<p>Again, <strong>the type comes after the argument&rsquo;s name</strong>.</p>

<p>Just like in Go and C, <strong>functions cannot be overloaded</strong>. This simplifies the code and improves maintainability and readability.</p>

<p>Functions can be used before their declaration: <code>add</code> and <code>sub</code> are declared after main, but can still be called from main. This is true for all declarations in V and eliminates(消除) the need of header files or thinking about the order of files and declarations.</p>

<h2 id="variables">Variables</h2>

<pre><code class="language-v">name := 'Bob' 
age := 20
large_number := i64(9999999999)
println(name)
println(age)
println(large_number) 
</code></pre>

<p>Variables are declared and initialized with <code>:=</code>. This is the only way to declare variables in V. This means that <strong>variables always have an initial value</strong>.</p>

<p>The variable&rsquo;s type is inferred(推测) from the value on the right hand side. To force a different type, use type conversion: the expression <code>T(v)</code> converts the value v to the type T.</p>

<p>Unlike most other languages, <strong>V only allows defining variables in functions. Global (module level) variables are not allowed. There&rsquo;s no global state in V.</strong></p>

<pre><code class="language-v">mut age := 20
println(age)
age = 21
println(age)
</code></pre>

<p>To change the value of the variable use <code>=</code>. In V, variables are immutable(不可变的) by default. To be able to change the value of the variable, you have to declare it with <code>mut</code>.</p>

<p>The difference between <code>:=</code> and <code>=</code>
<code>:=</code> is used for declaring and initializing, <code>=</code> is used for assigning.</p>

<pre><code class="language-v">fn main() {
	age := 21
    // println(age)
}
</code></pre>

<p>This code will not compile either, because <strong>unused variables result in a compilation error</strong>(which is like go but go is more strict).</p>

<pre><code class="language-v">fn main() {
	a := 10 
	if true {
		a := 20
	} 
}
</code></pre>

<p>Unlike most languages, <strong>variable shadowing is not allowed</strong>. Declaring a variable with a name that is already used in a parent scope will result in a compilation error.</p>

<h2 id="basic-types">Basic types</h2>

<pre><code>bool

string

i8  i16  i32  i64      i128 (soon)
u8  u16  u32  u64      u128 (soon) 

byte // alias for u8  
int  // alias for i32  
rune // alias for i32, represents a Unicode code point  

f32 f64

byteptr
voidptr
</code></pre>

<p>Please note that unlike C and Go, <strong>int is always a 32 bit integer</strong>.</p>

<h2 id="strings">Strings</h2>

<pre><code class="language-v">name := 'Bob' 
println('Hello, $name!')  // `$` is used for string interpolation 
println(name.len) 

bobby := name + 'by' // + is used to concatenate strings 
println(bobby) // ==&gt; &quot;Bobby&quot;  

println(bobby.substr(1, 3)) // ==&gt; &quot;ob&quot;  
// println(bobby[1:3]) // This syntax will most likely replace the substr() method   
</code></pre>

<p>In V, a string is a <code>read-only array of bytes</code>. String data is encoded using UTF-8.</p>

<p>Both single and double quotes can be used to denote strings (TODO: double quotes are not supported yet). For consistency, vfmt converts double quotes to single quotes unless the string contains a single quote character.</p>

<p>Strings are immutable. This means that the substring function is very efficient: no copying is performed, no extra allocations required.</p>

<p>All operators in V must have values of the same type on both sides. This code will not compile if age is an int:
<code>println('age = ' + age)</code>. We have to either convert age to a string: <code>println('age = ' + age.str())</code> or use string interpolation(插值) (preferred):<code>println('age = $age')</code></p>

<h2 id="arrays">Arrays</h2>

<pre><code class="language-v">nums := [1, 2, 3]
println(nums)
println(nums[1]) // ==&gt; &quot;2&quot; 

mut names := ['John']
names &lt;&lt; 'Peter' 
names &lt;&lt; 'Sam' 
// names &lt;&lt; 10  &lt;-- This will not compile. `names` is an array of strings. 
println(names.len) // ==&gt; &quot;3&quot; 
println('Alex' in names) // ==&gt; &quot;false&quot; 

// We can also preallocate a certain amount of elements. 
nr_ids := 50
mut ids := [0 ; nr_ids] // This creates an array with 50 zeroes 
</code></pre>

<p><strong>Array type is determined by the first element</strong>: [1, 2, 3] is an array of ints(<code>[]int</code>).
[&lsquo;a&rsquo;, &lsquo;b&rsquo;] is an array of strings (<code>[]string</code>).</p>

<p>All elements must have the same type. [1, &lsquo;a&rsquo;] will not compile.</p>

<p><code>&lt;&lt;</code> is an operator that appends a value to the end of the array.</p>

<p><code>.len</code> field returns the length of the array. Note, that it&rsquo;s a read-only field, and it can&rsquo;t be modified by the user. All exported fields are read-only by default in V.</p>

<p><code>val in array</code> returns true if the array contains val.</p>

<h2 id="maps">Maps</h2>

<pre><code class="language-v">mut m := map[string]int{} // Only maps with string keys are allowed for now  
m['one'] = 1
println(m['one']) // ==&gt; &quot;1&quot;  
println(m['bad_key']) // ==&gt; &quot;0&quot;  
// TODO: implement a way to check if the key exists 

numbers := { // TODO: this syntax is not implemented yet  
	'one': 1,
	'two': 2,
} 
</code></pre>

<h2 id="if">If</h2>

<pre><code class="language-v">a := 10 
b := 20 
if a &lt; b { 
	println('$a &lt; $b') 
} else if a &gt; b { 
	println('$a &gt; $b') 
} else { 
	println('$a == $b') 
} 
</code></pre>

<p><code>if</code> statements are pretty straightforward(直截了当的) and similar to most other languages.</p>

<p>Unlike other C-like languages, there are no parentheses(括号) surrounding the condition, and the braces are always required.</p>

<p><code>if</code> can be used as an expression(like lambda?):</p>

<pre><code class="language-v">num := 777
s := if num % 2 == 0 {
	'even'
}
else {
	'odd'
}
println(s) // ==&gt; &quot;odd&quot;
</code></pre>

<p><code>In</code> operator : check whether an array contains an element.</p>

<pre><code class="language-v">nums := [1, 2, 3]
println(1 in nums) // ==&gt; true 
</code></pre>

<p>It&rsquo;s also useful for writing more clear and compact(紧凑的) boolean expressions:</p>

<pre><code class="language-v">if parser.token == .plus || parser.token == .minus || parser.token == .div || parser.token == .mult {
	... 
} 

if parser.token in [.plus, .minus, .div, .mult] {
	... 
} 
</code></pre>

<p>V optimizes such expressions, so both <code>if</code> statements above produce the same machine code, no arrays are created.</p>

<h2 id="for-loop">For loop</h2>

<p>V has only one looping construct: <code>for</code>.</p>

<pre><code class="language-v">numbers := [1, 2, 3, 4, 5]
for num in numbers {
	println(num)
}
names := ['Sam', 'Peter']
for i, name in names {
	println('$i) $name')  // Output: 0) Sam
}                             //         1) Peter
</code></pre>

<p>The <code>for .. in</code> loop is used for going through elements of an array. If an index is required, an alternative form for index, value in can be used.</p>

<p>Note, that the value is read-only. If you need to modify the array while looping, you have to use indexing:</p>

<pre><code class="language-v">mut numbers := [1, 2, 3, 4, 5]
for i, num in numbers {
	println(num)
	numbers[i] = 0
}
</code></pre>

<p>println(sum) // ==&gt; &ldquo;5050&rdquo;</p>

<p>This form of the loop is similar to while loops in other languages.</p>

<p>The loop will stop iterating once the boolean condition evaluates to false.</p>

<p>Again, there are no parentheses surrounding the condition, and the braces are always required.</p>

<p>The condition can be omitted, this results in an infinite loop.</p>

<pre><code class="language-v">for i := 0; i &lt; 10; i++ {
	println(i)
}
</code></pre>

<p>Finally, there&rsquo;s the traditional C style for loop. It&rsquo;s safer than the <code>while</code> form because with the latter it&rsquo;s easy to forget to update the counter and get stuck in an infinite loop.</p>

<p>Here <code>i</code> doesn&rsquo;t need to be declared with <code>mut</code> since it&rsquo;s always going to be mutable by definition.</p>

<h2 id="switch">Switch</h2>

<pre><code class="language-v">os := 'windows' 
print('V is running on ')
switch os {
case 'darwin':
	println('macOS.')
case 'linux':
	println('Linux.')
default:
	println(os) 
}
// TODO: replace with match expressions 
</code></pre>

<p>A <code>switch</code> statement is a shorter way to write a sequence of <code>if - else</code> statements. It runs the first case whose value is equal to the condition expression.</p>

<p>Unlike C, break statement is not needed at the end of every block, but the same with go.</p>

<h2 id="structs">Structs</h2>

<pre><code class="language-v">struct Point {
	x int
	y int 
} 

p := Point{
	x: 10 
	y: 20 
} 
println(p.x) // Struct fields are accessed using a dot 

</code></pre>

<p>Structs are allocated on the stack. To allocate a struct on the heap and get a pointer to it, use the <code>&amp;</code> prefix:</p>

<pre><code class="language-v">pointer := &amp;Point{10, 10}  // Alternative initialization syntax for structs with 3 fields or fewer
println(pointer.x) // Pointers have the same syntax for accessing fields  
</code></pre>

<p>V doesn&rsquo;t have subclassing, but it supports embedded structs:</p>

<pre><code class="language-v">// TODO: this will be implemented later in June
struct Button {
	Widget
	title string
}

button := new_button('Click me')
button.set_pos(x, y)

// Without embedding we'd have to do
button.widget.set_pos(x,y)
</code></pre>

<h2 id="access-modifiers">Access modifiers</h2>

<p>Struct fields are private and immutable by default (making structs immutable as well). Their access modifiers can be changed with pub and mut. In total, there are 5 possible options:</p>

<pre><code class="language-v">struct Foo {
	a int     // private immutable (default) 
mut: 
	b int     // private mutable 
	c int     // (you can list multiple fields with the same access modifier)   
pub: 
	d int     // public immmutable (readonly) 
pub mut: 
	e int     // public, but mutable only in parent module  
pub mut mut: 
	f int 	  // public and mutable both inside and outside parent module  
}                 // (not recommended to use, that's why it's so verbose) 
</code></pre>

<p>For example, here&rsquo;s the string type defined in the builtin module:</p>

<pre><code class="language-v">struct string {
	str byteptr
pub:
	len int
}
</code></pre>

<p>It&rsquo;s easy to see from this definition that string is an immutable type.</p>

<p>The byte pointer with the string data is not accessible outside builtin at all. len field is public, but not mutable.</p>

<pre><code class="language-v">fn main() {
	str := 'hello' 
	len := str.len // OK  
	str.len++      // Compilation error  
} 

</code></pre>

<h2 id="methods">Methods</h2>

<pre><code class="language-v">struct User {
	age int 
} 

fn (u User) can_register() bool {
	return u.age &gt; 16 
} 

user := User{age: 10} 
println(user.can_register()) // ==&gt; &quot;false&quot;  

user2 := User{age: 20} 
println(user2.can_register()) // ==&gt; &quot;true&quot;  
</code></pre>

<p><strong>V doesn&rsquo;t have classes. But you can define methods on types.</strong></p>

<p><strong>A method is a function with a special receiver argument.</strong></p>

<p>The receiver appears in its own argument list between the fn keyword and the method name.</p>

<p>In this example, the <code>can_register</code> method has a receiver of type <code>User</code> named <code>u</code>. The convention(公约) is not to use receiver names like self or this, but a short, preferably one letter long, name.</p>

<h2 id="pure-functions-by-default">Pure functions by default</h2>

<p>V functions are pure by default, meaning that their return values are only determined by their arguments, and their evaluation has no side effects.</p>

<p>This is achieved by lack of global variables and all function arguments being immutable by default, even when references are passed.</p>

<p>V is not a pure functional language however. It is possible to modify function arguments by using the same keyword mut:</p>

<pre><code class="language-v">struct User {
mut:
	is_registered bool 
} 

fn (u mut User) register() {
	u.is_registered = true 
} 

mut user := User{} 
println(user.is_registered) // ==&gt; &quot;false&quot;  
user.register() 
println(user.is_registered) // ==&gt; &quot;true&quot;  
</code></pre>

<p>In this example, the receiver (which is simply the first argument) is marked as mutable, so <code>register()</code> can change the user object. The same works with non-receiver arguments:</p>

<pre><code class="language-v">fn multiply_by_2(arr mut []int) {
	for i := 0; i &lt; arr.len; i++ {
		arr[i] *= 2
	}
}

mut nums := [1, 2, 3]
multiply_by_2(mut nums)
println(nums) // ==&gt; &quot;[2, 4, 6]&quot;
</code></pre>

<p>Note, that you have to <strong>add mut before nums when calling this function</strong>. This makes it clear that the function being called will modify the value.</p>

<p>It is preferable(更好) to return values instead of modifying arguments. Modifying arguments should only be done in performance-critical parts of your application to reduce allocations and copying.</p>

<p>Use <code>user.register()</code> or <code>user = register(user)</code> instead of <code>register(mut user)</code>.</p>

<p>V makes it easy to return a modifed version of an an object:</p>

<pre><code class="language-v">fn register(u User) User { 
	return { u | is_registered: true } 
}

user = register(user) 
</code></pre>

<h2 id="constants">Constants</h2>

<pre><code class="language-v">const (
	PI    = 3.14
	World = '世界'
) 

println(PI)
println(World)
</code></pre>

<p>Constants are declared with <code>const</code>. They can only be defined at the module level (outside of functions).</p>

<p>Constant names must be capitalized. This helps distinguish them from variables.</p>

<p>Constant values can never be changed.</p>

<p>V constants are more flexible than in most languages. You can assign more complex values:</p>

<pre><code class="language-v">struct Color {
        r int
        g int
        b int
}

fn (c Color) str() string { return '{$c.r, $c.g, $c.b}' }

fn rgb(r, g, b int) Color { return Color{r: r, g: g, b: b} }

const (
        Numbers = [1, 2, 3]

        Red  = Color{r: 255, g: 0, b: 0}
        Blue = rgb(0, 0, 255)
)

println(Numbers)
println(Red)
println(Blue)
</code></pre>

<p>Global variables are not allowed, so this can be really useful.</p>

<h2 id="modules">Modules</h2>

<p>V is a very modular language. Creating reusable modules is encouraged and is very simple. To create a new module, <strong>create a directory with your module&rsquo;s name and .v files with code</strong>:</p>

<pre><code>cd ~/code/modules
mkdir mymodule
vim mymodule/mymodule.v

// mymodule.v
module mymodule

// To export a function we have to use `pub`
pub fn say_hi() {
	println('hello from mymodule!')
}
</code></pre>

<p>You can have as many .v files in mymodule/ as you want.</p>

<p>Build it with <code>v -lib ~/code/modules/mymodule</code>.</p>

<p>That&rsquo;s it, you can now use it in your code:</p>

<pre><code class="language-v">module main

import mymodule

fn main() {
	mymodule.say_hi()
}
</code></pre>

<p>Note that you have to specify the module every time you call an external function. This may seem verbose(冗长) at first, but it makes code much <strong>more readable and easier to understand</strong>, since it&rsquo;s always clear which function from which module is being called. Especially in large code bases.</p>

<p>Module names should be short, under 10 characters. Circular imports are not allowed.</p>

<p>You can create modules anywhere.</p>

<p>All modules are compiled statically into a single executable.</p>

<h2 id="interfaces">Interfaces</h2>

<pre><code class="language-v">struct Dog {}
struct Cat {}

fn (d Dog) speak() string { 
	return 'woof'
} 

fn (c Cat) speak() string { 
	return 'meow' 
} 

interface Speaker {
	speak() string
}

fn perform(s Speaker) { 
	println(s.speak())
} 

dog := Dog{} 
cat := Cat{} 
perform(dog) // ==&gt; &quot;woof&quot; 
perform(cat) // ==&gt; &quot;meow&quot; 
</code></pre>

<p><strong>A type implements an interface by implementing its methods</strong>. There is no explicit(显式) declaration of intent, no &ldquo;implements&rdquo; keyword.</p>

<h2 id="enums">Enums</h2>

<pre><code class="language-v">enum Color {
	red green blue 
} 

mut color := Color.red
// V knows that `color` is a `Color`. No need to use `Color.green` here.
color = .green  // . operator 
println(color) // ==&gt; &quot;1&quot;  TODO: print &quot;green&quot;?  
</code></pre>

<h2 id="option-result-types-error-handling">Option/Result types &amp; error handling</h2>

<pre><code class="language-v">struct User {
	id int 
	name string
} 

struct Repo {
	users []User 
} 

fn new_repo() Repo {
	return Repo {
		users: [User{1, 'Andrew'}, User {2, 'Bob'}, User {10, 'Charles'}]
	}
} 

fn (r Repo) find_user_by_id(id int) ?User { 
	for user in r.users {
		if user.id == id {
			// V automatically wraps this into an option type  
			return user 
		} 
	} 
	return error('User $id not found') 
} 

fn main() {
	repo := new_repo() 
	user := repo.find_user_by_id(10) or { // Option types must be handled by `or` blocks  
		return  // `or` block must end with `return`, `break`, or `continue`  
	} 
	println(user.id) // ==&gt; &quot;10&quot;  
	println(user.name) // ==&gt; 'Charles'
}
</code></pre>

<p>V combines Option and Result into one type, so you don&rsquo;t need to decide which one to use.</p>

<p>The amount of work required to &ldquo;upgrade&rdquo; a function to an optional function is minimal: you have to add a <code>?</code> to the return type and return an error when something goes wrong.</p>

<p>If you don&rsquo;t need to return an error, you can simply return None. (TODO: None is not implemented yet).</p>

<p>This is the primary way of handling errors in V. They are still values, like in Go, but the advantage is that errors can&rsquo;t be unhandled, and handling them is a lot less verbose(冗长).</p>

<p>You can also propagate(传播) errors:</p>

<pre><code class="language-v">resp := http.get(url)?
println(resp.body)
</code></pre>

<p>http.get returns <code>?http.Response</code>. It was called with <code>?</code>, so the <code>error</code> is propagated to the calling function or in case of main leads to a panic.</p>

<p>Basically the code above is a shorter version of</p>

<pre><code class="language-v">resp := http.get(url) or {
	panic(err)
}
println(resp.body)
</code></pre>

<h2 id="generics-july">Generics (July)</h2>

<pre><code class="language-v">struct Repo⟨T⟩ {
	db DB
}

fn new_repo⟨T⟩(db DB) Repo⟨T⟩ {
	return Repo⟨T⟩{db: db}
}

// This is a generic function. V will generate it for every type it's used with. 
fn (r Repo⟨T⟩) find_by_id(id int) ?T {  
	table_name := T.name // in this example getting the name of the type gives us the table name 
	return r.db.query_one⟨T⟩('select * from $table_name where id = ?', id)
}

db := new_db()
users_repo := new_repo⟨User⟩(db)
posts_repo := new_repo⟨Post⟩(db)
user := users_repo.find_by_id(1)? 
post := posts_repo.find_by_id(1)? 
</code></pre>

<p>For readability, <code>⟨⟩</code> are allowed instead of <code>&lt;&gt;</code>. vfmt automatically replaces <code>&lt;&gt;</code> with <code>⟨⟩</code>.</p>

<h2 id="concurrency">Concurrency</h2>

<p>The concurrency model is very similar to Go. To run foo() concurrently, just call it with go foo(). Right now, it launches the function in a new system thread. Soon goroutines and the scheduler will be implemented.</p>

<h2 id="decoding-json">Decoding JSON</h2>

<pre><code class="language-v">struct User {
	name string
	age  int 
	foo  Foo    [skip]  // Use `skip` attribute to skip certain fields 
} 

data := '{ &quot;name&quot;: &quot;Frodo&quot;, &quot;age&quot;: 25 }'
user := json.decode(User, data) or {
	eprintln('Failed to decode json')
	return 
} 
println(user.name)
println(user.age) 
</code></pre>

<p>JSON is very popular nowadays, that&rsquo;s why JSON support is built in.</p>

<p>The first argument of the <code>json.decode</code> function is the type to decode to. The second argument is the JSON string.</p>

<p>V generates code for JSON encoding and decoding. No runtime reflection is used. This results in much better performance.</p>

<h2 id="testing">Testing</h2>

<pre><code class="language-v">// hello.v 
fn hello() string {
	return 'Hello world'
} 

// hello_test.v 
fn test_hello() {
    assert hello() == 'Hello world'
} 
</code></pre>

<p>All test functions have to be placed in <code>*_test.v</code> files and begin with <code>test_</code>. To run the tests do <code>v hello_test.v</code>. To test an entire module, do <code>v test mymodule</code>.</p>

<h2 id="memory-management">Memory management</h2>

<p>There&rsquo;s <strong>no garbage collection or reference counting</strong>. V cleans up what it can during compilation. For example:</p>

<pre><code class="language-v">fn draw_text(s string, x, y int) {
	...
}

fn draw_scene() {
	... 
	draw_text('hello $name1', 10, 10)
	draw_text('hello $name2', 100, 10)
	draw_text(strings.repeat('X', 10000), 10, 50)
	... 
}
</code></pre>

<p>The strings don&rsquo;t escape <code>draw_text</code>, so they are cleaned up when the function exits.</p>

<p>In fact, the first two calls won&rsquo;t result in any allocations at all. These two strings are small, V will use a preallocated buffer for them.</p>

<p>For more complex cases manual memory management is required. This will be fixed soon.</p>

<p>V will detect memory leaks at runtime and report them. To clean up, for example, an array, use the <code>free()</code> method:</p>

<pre><code class="language-v">numbers := [0; 1000000] 
...
numbers.free()
</code></pre>

<h2 id="defer">Defer</h2>

<p>TODO</p>

<h2 id="vfmt">vfmt</h2>

<p>TODO</p>

<p><strong>Advanced Topics</strong></p>

<hr />

<h2 id="calling-c-functions-from-v">Calling C functions from V</h2>

<pre><code class="language-v">#flag -lsqlite3

#include &quot;sqlite3.h&quot;

struct C.sqlite3 
struct C.sqlite3_stmt 

fn C.sqlite3_column_int(C.sqlite_stmt, int) int 

fn main() {
	path := 'sqlite3_users.db' 
	db := &amp;C.sqlite3{} 
	C.sqlite3_open(path.cstr(), &amp;db)

	query := 'select count(*) from users' 
	stmt := &amp;C.sqlite3_stmt{} 
	C.sqlite3_prepare_v2(db, query.cstr(), - 1, &amp;stmt, 0)
	C.sqlite3_step(stmt) 
	nr_users := C.sqlite3_column_int(res, 0)
	C.sqlite3_finalize(res)
	println(nr_users) 
} 
</code></pre>

<h2 id="compile-time-if">Compile time if</h2>

<pre><code class="language-v">$if windows {
	println('Windows')  
}  
$if linux {
	println('Linux') 
} 
$if mac {
	println('macOS') 
} 
</code></pre>

<p><code>Compile time if</code> starts with a <code>$</code>. Right now it can only be used to detect an OS.</p>

<h2 id="reflection-via-codegen">Reflection via codegen</h2>

<p>Having built-in JSON support is nice, but V also allows you to create efficient serializers for anything:</p>

<pre><code class="language-v">// TODO: planned in June
fn decode&lt;T&gt;(data string) T {
        mut result := T{}
        for field in T.fields {
                if field.typ == 'string' {
                        result.$field = get_string(data, field.name)
                } else if field.typ == 'int' {
                        result.$field = get_int(data, field.name)
                }
        }
        return result
}

// generates to:
fn decode_User(data string) User {
        mut result := User{}
        result.name = get_string(data, 'name')
        result.age = get_int(data, 'age')
        return result
}
</code></pre>

<h2 id="limited-operator-overloading">Limited operator overloading</h2>

<pre><code class="language-v">struct Vec {
	x int
	y int
}

fn (a Vec) str() string { 
	return '{$a.x, $a.y}' 
}

fn (a Vec) + (b Vec) Vec {
	return Vec {
		a.x + b.x, 
		a.y + b.y 
	}
}

fn (a Vec) - (b Vec) Vec {
	return Vec {
		a.x - b.x, 
		a.y - b.y
	}
}

fn main() { 
	a := Vec{2, 3}
	b := Vec{4, 5}
	println(a + b) // ==&gt; &quot;{6, 8}&quot;  
	println(a - b) // ==&gt; &quot;{-2, -2}&quot;  
} 
</code></pre>

<p>Operator overloading goes against V&rsquo;s philosophy(哲学) of simplicity and predictability. But since scientific and graphical applications are among V&rsquo;s domains, operator overloading is very important to have in order to improve readability:</p>

<p><code>a.add(b).add(c.mul(d))</code> is a lot less readable than <code>a + b + c * d</code>.</p>

<p>To improve safety and maintainability, operator overloading has several limitations:</p>

<ul>
<li>It&rsquo;s only possible to overload +, -, *, / operators.</li>
<li>Calling other functions inside operator functions is not allowed.</li>
<li>Operator functions can&rsquo;t modify their arguments.</li>
<li>Both arguments must have the same type (just like with all operators in V).</li>
</ul>

<h2 id="translating-c-c-to-v">Translating C/C++ to V</h2>

<p>TODO: translating C to V will be available in June. C++ to V will be available later this year.</p>

<p>V can translate your C/C++ code to human readable V code. Let&rsquo;s create a simple program test.cpp first:</p>

<pre><code class="language-c">#include &lt;vector&gt;
#include &lt;string&gt;
#include &lt;iostream&gt;

int main() {
        std::vector&lt;std::string&gt; s;
        s.push_back(&quot;V is &quot;);
        s.push_back(&quot;awesome&quot;);
        std::cout &lt;&lt; s.size() &lt;&lt; std::endl;
        return 0;
} 
</code></pre>

<p>Run <code>v translate test.cpp</code> and V will generate test.v:</p>

<pre><code class="language-v">fn main {
        mut s := []
	s &lt;&lt; 'V is '
	s &lt;&lt; 'awesome'
	println(s.len) 
} 
</code></pre>

<p>When should you translate C code and when should you simply call C code from V?</p>

<p>If you have well-written, well-tested C code, then of course you can always simply call this C code from V.</p>

<p>Translating it to V gives you several advantages:</p>

<ul>
<li><p>If you plan to develop that code base, you now have everything in one language, which is much safer and easier to develop in that C.</p></li>

<li><p>Cross-compilation becomes a lot easier. You don&rsquo;t have to worry about it at all.</p></li>

<li><p>No more build flags and include files either.</p></li>
</ul>

<h2 id="hot-code-reloading">Hot code reloading</h2>

<p>TODO</p>

<h2 id="cross-compilation">Cross compilation</h2>

<p>To cross compile your project simply run</p>

<p><code>v -os windows</code> or <code>v -os linux</code> .</p>

<p>(Cross compiling for macOS is temporarily not possible.)</p>

<p>If you don&rsquo;t have any C dependencies, that&rsquo;s all you need to do. This works even when compiling GUI apps using the ui module or graphical apps using gg.</p>

<h2 id="cross-platform-shell-scripts-in-v">Cross-platform shell scripts in V</h2>

<p>(Coming later in June.)</p>

<p>V can be used as an alternative to Bash to write deployment scripts, build scripts, etc.</p>

<p>The advantage of using V for this is the simplicity and predictability of the language, and cross-platform support. &ldquo;V scripts&rdquo; run on Unix-like systems as well as on Windows.</p>

<p>Start your program with a <code>#v</code> directive. It will make all functions in the os module global (so that you can use ls() instead of os.ls(), for example).</p>

<pre><code class="language-v">#v 

rm('build/*') 
// Same as:  
for file in ls('build/') {
	rm(file) 
} 

mv('*.v', 'build/') 
// Same as:  
for file in ls('.') {
	if file.ends_with('.v') { 
		mv(file, 'build/') 
	} 
} 
</code></pre>

<p>Now you can either compile this like a normal V program and get an executable you can deploy and run anywhere: <code>v deploy.v &amp;&amp; ./deploy</code></p>

<p>Or just run it more like a traditional bash script: <code>v run deploy.v</code></p>

<h2 id="appendix-i-keywords">Appendix I: Keywords</h2>

<p>V has 22 keywords:</p>

<pre><code>break 
const  
continue 
defer 
else 
enum 
fn
for
go
goto
if
import
in 
interface 
match 
module 
mut 
or 
pub 
return
struct
type 
</code></pre>

<h2 id="appendix-ii-operators">Appendix II: Operators</h2>

<table>
<thead>
<tr>
<th>operator</th>
<th>name</th>
<th>values</th>
</tr>
</thead>

<tbody>
<tr>
<td><code>+</code></td>
<td>sum</td>
<td>integers, floats, strings</td>
</tr>

<tr>
<td><code>-</code></td>
<td>difference</td>
<td>integers, floats</td>
</tr>

<tr>
<td><code>*</code></td>
<td>product</td>
<td>integers, floats</td>
</tr>

<tr>
<td><code>/</code></td>
<td>quotient</td>
<td>integers, floats</td>
</tr>

<tr>
<td><code>%</code></td>
<td>remainder</td>
<td>integers</td>
</tr>

<tr>
<td><code>&amp;</code></td>
<td>bitwise AND</td>
<td>integers</td>
</tr>

<tr>
<td><code>\</code></td>
<td>bitwise OR</td>
<td>integers</td>
</tr>

<tr>
<td><code>^</code></td>
<td>bitwise XOR</td>
<td>integers</td>
</tr>

<tr>
<td><code>&lt;&lt;</code></td>
<td>left shift</td>
<td>integer &lt;&lt; unsigned integer</td>
</tr>

<tr>
<td><code>&gt;&gt;</code></td>
<td>right shift</td>
<td>integer &gt;&gt; unsigned integer</td>
</tr>
</tbody>
</table>
                        </div>

                        


                        


                        <div class="post-meta meta-tags">
                            
                            <ul class="clearfix">
                                
                                <li><a href="https://otswang.gitee.io/hugo/tags/vlang">vlang</a></li>
                                
                            </ul>
                            
                        </div>
                    </article>
                    
    

    
    
                </div>
            </div>
            <div id="secondary">

    <section class="widget">
        <form id="search" action="//www.google.com/search" method="get" accept-charset="utf-8" target="_blank" _lpchecked="1">
      
      <input type="text" name="q" maxlength="20" placeholder="Search">
      <input type="hidden" name="sitesearch" value="https://otswang.gitee.io/hugo/">
      <button type="submit" class="submit icon-search"></button>
</form>
    </section>

    
    <div class="clear">
        <div class="toc-article">
            <div class="toc-title">文章目录</dixsv>
            <nav id="TableOfContents">
<ul>
<li>
<ul>
<li><a href="#introduction">Introduction</a></li>
<li><a href="#functions">Functions</a></li>
<li><a href="#variables">Variables</a></li>
<li><a href="#basic-types">Basic types</a></li>
<li><a href="#strings">Strings</a></li>
<li><a href="#arrays">Arrays</a></li>
<li><a href="#maps">Maps</a></li>
<li><a href="#if">If</a></li>
<li><a href="#for-loop">For loop</a></li>
<li><a href="#switch">Switch</a></li>
<li><a href="#structs">Structs</a></li>
<li><a href="#access-modifiers">Access modifiers</a></li>
<li><a href="#methods">Methods</a></li>
<li><a href="#pure-functions-by-default">Pure functions by default</a></li>
<li><a href="#constants">Constants</a></li>
<li><a href="#modules">Modules</a></li>
<li><a href="#interfaces">Interfaces</a></li>
<li><a href="#enums">Enums</a></li>
<li><a href="#option-result-types-error-handling">Option/Result types &amp; error handling</a></li>
<li><a href="#generics-july">Generics (July)</a></li>
<li><a href="#concurrency">Concurrency</a></li>
<li><a href="#decoding-json">Decoding JSON</a></li>
<li><a href="#testing">Testing</a></li>
<li><a href="#memory-management">Memory management</a></li>
<li><a href="#defer">Defer</a></li>
<li><a href="#vfmt">vfmt</a></li>
<li><a href="#calling-c-functions-from-v">Calling C functions from V</a></li>
<li><a href="#compile-time-if">Compile time if</a></li>
<li><a href="#reflection-via-codegen">Reflection via codegen</a></li>
<li><a href="#limited-operator-overloading">Limited operator overloading</a></li>
<li><a href="#translating-c-c-to-v">Translating C/C++ to V</a></li>
<li><a href="#hot-code-reloading">Hot code reloading</a></li>
<li><a href="#cross-compilation">Cross compilation</a></li>
<li><a href="#cross-platform-shell-scripts-in-v">Cross-platform shell scripts in V</a></li>
<li><a href="#appendix-i-keywords">Appendix I: Keywords</a></li>
<li><a href="#appendix-ii-operators">Appendix II: Operators</a></li>
</ul></li>
</ul>
</nav>
        </div>
    </div>
    

</div>
        </div>
    </div>
</div>
<footer id="footer">
    <div class="container">
        &copy; 2020 <a href="https://otswang.gitee.io/hugo/">The Sky of OtsWang By OtsWang</a>.
        Powered by <a rel="nofollow noreferer noopener" href="https://gohugo.io" target="_blank">Hugo</a>.
        <a href="https://www.flysnow.org/" target="_blank">Theme</a> based on <a href="https://github.com/Dudiao137/maupassant-hugo" target="_blank">maupassant-ots</a>.
        
    </div>
</footer>


    <script type="text/javascript">
    
    (function(){
        $("pre code").parent().addClass("line-numbers")
    }())

    window.MathJax = {
        tex2jax: {
            inlineMath: [ ['$','$'] ],
            processEscapes: true
        }
    };
    </script>
    <script type="text/javascript" src="/hugo/js/prism.js" async="true"></script>
    <script src='https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.5/MathJax.js?config=TeX-MML-AM_CHTML' async></script>

<a id="rocket" href="#top"></a>
<script type="text/javascript" src="/hugo/js/totop.js?v=0.0.0" async=""></script>







 
 <script src="https://mermaidjs.github.io/scripts/mermaid.min.js"></script>
 <script>
       mermaid.initialize({ startOnLoad: true });
 </script>
</body>
</html>
